package com.banmao.snake_core.util;

import javafx.embed.swing.SwingFXUtils;
import javafx.scene.image.WritableImage;

import javax.swing.*;
import javax.swing.filechooser.FileSystemView;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 *  图标工具
 */
public class FileIconUtil {

    private static final HashMap<String, WritableImage> mapOfFileExtToSmallIcon = new HashMap<String, WritableImage>();

    private static final String DIRECTORY_KEY = "__DIRECTORY__";
    private static final String ROOT_DIRECTORY_KEY = "__ROOT_DIRECTORY__";
    private static final String HASNOEXT_KEY = "__HASNOEXT__";

    private static String getFileExt(String fname) {
        String finalFname;
        // 切分路径，提取文件名
        // Matcher.quoteReplacement(File.separator) 避免转义问题
        String[] split = fname.split(Matcher.quoteReplacement(File.separator));
        if(split.length < 2) {
            finalFname = fname;
        } else {
            finalFname = split[split.length - 1];
        }

        String ext;
        int p = finalFname.lastIndexOf('.');
        if (p > 0) {
            ext = finalFname.substring(p);
        } else {
            return HASNOEXT_KEY;
        }
        return ext.toLowerCase();
    }

    public static WritableImage getFileIcon(String fname) {

        boolean isFolder = false; // 是否文件夹
        boolean hasNoExt = false; // 是否有扩展名

        File file = new File(fname);

        // 判断是否是盘符
        boolean isROOTDIR = judgeRootDIR(fname);

        if(isROOTDIR && file.isDirectory() && mapOfFileExtToSmallIcon.get(ROOT_DIRECTORY_KEY) != null) {
            return mapOfFileExtToSmallIcon.get(ROOT_DIRECTORY_KEY);
        }

        if(!isROOTDIR && file.isDirectory() && mapOfFileExtToSmallIcon.get(DIRECTORY_KEY) != null) {
            return mapOfFileExtToSmallIcon.get(DIRECTORY_KEY);
        }

        final String ext = getFileExt(fname);
        if(file.isFile() && HASNOEXT_KEY.equals(ext)) {
            hasNoExt = true;
            if(mapOfFileExtToSmallIcon.get(HASNOEXT_KEY) != null) {
                return mapOfFileExtToSmallIcon.get(HASNOEXT_KEY);
            }
        }

        WritableImage fileIcon = mapOfFileExtToSmallIcon.get(ext);
        if (fileIcon == null) {

            Icon jswingIcon = null;

            if (file.exists()) {
                jswingIcon = getJSwingIconFromFileSystem(file);
                if(file.isDirectory()) {
                    isFolder = true;
                }
            }
            else {
                File tempFile = null;
                try {
                    tempFile = File.createTempFile("icon", ext);
                    jswingIcon = getJSwingIconFromFileSystem(tempFile);
                }
                catch (IOException ignored) {
                    // Cannot create temporary file.
                }
                finally {
                    if (tempFile != null) tempFile.delete();
                }
            }

            if (jswingIcon != null) {
                fileIcon = jswingIconToImage(jswingIcon);
                if(isROOTDIR) {
                    mapOfFileExtToSmallIcon.put(ROOT_DIRECTORY_KEY, fileIcon);
                } else if (isFolder) {
                    mapOfFileExtToSmallIcon.put(DIRECTORY_KEY, fileIcon);
                } else if (hasNoExt) {
                    // 没有扩展名的文件
                    mapOfFileExtToSmallIcon.put(HASNOEXT_KEY, fileIcon);
                } else {
                    mapOfFileExtToSmallIcon.put(ext, fileIcon);
                }
            }
        }

        return fileIcon;
    }

    private static boolean judgeRootDIR(String fname) {
        String regex = "^([A-Za-z]:\\\\?)$";
        boolean matches = Pattern.matches(regex, fname);
        return matches;
    }

    private static Icon getJSwingIconFromFileSystem(File file) {

        // Windows {
        FileSystemView view = FileSystemView.getFileSystemView();
        Icon icon = view.getSystemIcon(file);
        // }

        // OS X {
        //final javax.swing.JFileChooser fc = new javax.swing.JFileChooser();
        //javax.swing.Icon icon = fc.getUI().getFileView(fc).getIcon(file);
        // }

        return icon;
    }

    private static WritableImage jswingIconToImage(Icon jswingIcon) {
        BufferedImage bufferedImage = new BufferedImage(jswingIcon.getIconWidth(), jswingIcon.getIconHeight(),
                BufferedImage.TYPE_INT_ARGB);
        jswingIcon.paintIcon(null, bufferedImage.getGraphics(), 0, 0);

        return SwingFXUtils.toFXImage(bufferedImage, null);
    }

}
